﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;

using Sampler;
using Shapes.Misc;
using Shapes.Geometry;
using Shapes.Misc.Appearance;
using ShapesExtensions;

namespace TestGame.Samples
{
    /// <summary>
    /// This Sample shows the collision between a shape and a Texture2D with a specified soure Rectangle.
    /// In fact there is a Shape created from the Texture2D to check collision.
    /// The Source Rectangle is moved and the other shape is moved by the mouse.
    /// If they collide, the source rectangle movement stops and the other shape is colorized.
    /// </summary>
    public class CollisionSample2 
#if XNA4
        :PhoneSample
#else
        : ZuneSample
#endif
    {
        const int TunnelWidth = 58;
        const int MaxPosition = 740;
        const int Velocity = 30;
        const int DigitalMoveVelocitiy = 30;
        static readonly Color CollisionColor = Color.Red;
        static readonly Color NonCollisionColor = Color.LightGreen;

        #region Fields

        // a class which allows to draw a shape into a texture
        TextureGenerator _Generator;

        // the background texture
        Texture2D _TunnelSprite;
        // the SpriteShape can create a Shape from a Texture2D
        SpriteShape _TunnelShape;

        // the Border is just for a better appearence...
        Texture2D _BorderTexture;
        Brush _BorderBrush;

        // the shape controled by the mouse...
        Shape _MouseShape;
        // ... and it's graphical representation
        GeometrySprite _MouseSprite;

        // the position of the texture's source rectangle
        float _PosX = 0;

        #endregion

        public CollisionSample2(TextureGenerator textureGenerator)
            : base(
#if XNA4
            false,
#endif
            "Collision Sample 2:\n\n"
            + "Collision with an \n animated Texture2D.\n"
            + "press up and down to change \n the smiley's position")
        {
            _Generator = textureGenerator;
        }

        #region Initialize
        protected override void  Initialize()
        {

            // use the original texture for displaying
            _TunnelSprite = Game.Content.Load<Texture2D>("tunnel");
            // create a shape from this Texture with a Source-Rectangle
            _TunnelShape = new SpriteShape("tunnel", new Rectangle(0, 0, TunnelWidth, _TunnelSprite.Height), new AlphaThreshold(128));
            _TunnelShape.Position = new Vector2(100, 100);
            
#if ZUNE
            // for the zune we use a very simpified shape, 
            // because the zune is too slow for accurate collision detection (even with this small shape)
            _MouseShape = new Ellipse(15, 15);
            
#else
            Mouse.SetPosition(0, (int)(_TunnelShape.Position.X + 50));
            // generate a smiley shape and generate a texture from it.
            _MouseShape = GeometryTemplates.CreateSmiley(25);
#endif
            _MouseSprite = new GeometrySprite(_MouseShape, _Generator);//_Generator.GeometryFilled(_MouseShape);


            // create a rectangle Border to smooth the edges of the tunnel
            Rect hidingRect = new Rect(TunnelWidth, _TunnelShape.Height);
            hidingRect.Position = _TunnelShape.Position;
            // and draw the border to a texture.
            _BorderBrush = Brush.CreateFallOffBrush(10, 9);
            _BorderTexture = _Generator.GeometryBorder(hidingRect, _BorderBrush);

        }
        #endregion

        #region Update

        public override void Update(float seconds,
                                GamePadState currentButtons, GamePadState previousButtons,
                                KeyboardState currentKeys, KeyboardState previousKeys,
                                MouseState currentMouse, MouseState previousMouse)
        {
            float posY = _MouseShape.Position.Y;
#if WINDOWS
            // mouse movement
            if(Math.Abs(posY - currentMouse.Y) > 1)
                posY = currentMouse.Y;

            // move up or down with keyboard
            if (currentKeys.IsKeyDown(Keys.Up))
                posY -= (DigitalMoveVelocitiy * seconds);
            else if (currentKeys.IsKeyDown(Keys.Down))
                posY += (DigitalMoveVelocitiy * seconds);
#endif

            // move up or down with zune or game pad
            if (currentButtons.DPad.Up == ButtonState.Pressed)
                posY -= (DigitalMoveVelocitiy * seconds);
            else if (currentButtons.DPad.Down == ButtonState.Pressed)
                posY += (DigitalMoveVelocitiy * seconds);

            // the y position must be inside the _TunnelShape
            float min = (_TunnelShape.Position.Y + _TunnelShape.Height - _MouseShape.Height);
            float max = _TunnelShape.Position.Y;
            posY = Math.Min(posY, min);
            posY = Math.Max(posY, max);

#if WINDOWS
            // ensure that GamePad input sets the mouse to the right position
            // because if the mouse would stay, the picture would be reset on next Update
            if(currentMouse.Y <= min && currentMouse.Y >= max)
                Mouse.SetPosition(currentMouse.X, (int)posY);
#endif

            _MouseShape.Position = new Vector2(_TunnelShape.Center.X - _MouseShape.Width / 2, posY);


            // check collision
#if ZUNE    // for the zune we use a rough collision detection accuracy, because the zune is sooo slow...
            if (CollisionDetector2D.ShapeShapeIntersecting(_MouseShape, _TunnelShape, 4.0f))
#else
            if (CollisionDetector2D.ShapeShapeIntersecting(_MouseShape, _TunnelShape))
#endif
                _MouseSprite.Color = CollisionColor;//_IsColliding = true;
            else
                _MouseSprite.Color = NonCollisionColor;//_IsColliding = false;


            // Update SourceRect of TunnelShape (move a bit)
            if (_MouseSprite.Color == NonCollisionColor)
            {
                _PosX = (_PosX + seconds * Velocity) % MaxPosition;
                Rectangle rect = (Rectangle)_TunnelShape.SourceRect;
                _TunnelShape.SourceRect = new Rectangle((int)_PosX, rect.Y, rect.Width, rect.Height);
            }
        }
        #endregion

        #region Draw
        public override void Draw(SpriteBatch batch)
        {
            Game.GraphicsDevice.Clear(Color.DimGray);

            batch.Begin();

            // draw the background: use the original texture
            batch.Draw(_TunnelSprite, _TunnelShape.Position, _TunnelShape.SourceRect, Color.White);

            _MouseSprite.Draw(batch);

            // draw the border. Ask the Brush for the correct position.
            batch.Draw(_BorderTexture, _TunnelShape.Position - _BorderBrush.GetTextureOffset(), Color.Gray);

            batch.End();
        }
        #endregion
    }
}
